package com.open.exam.service;

import com.open.exam.common.CacheKey;
import com.open.exam.common.CommonFunction;
import com.open.exam.common.OperationResult;
import com.open.exam.databasemodel.*;
import com.open.exam.dto.AdminInfo;
import com.open.exam.dto.ExamCount;
import com.open.exam.dto.ExamPlanDetailViewModel;
import com.open.exam.dto.ExamPlanViewModel;
import com.open.exam.enums.DeploymentMode;
import com.open.exam.enums.ExamPlanSysState;
import com.open.exam.enums.OperationResultType;
import com.open.exam.enums.SubjectPaperStatus;
import com.open.exam.examplan.ExamSiteAppAccountRelation;
import com.open.exam.mapper.*;
import com.open.exam.utils.DateUtil;
import com.open.exam.utils.GsonUtil;
import com.open.exam.utils.RedisUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;

/**
 * @author 奶茶
 * Created on 2017/11/13.
 */
@Service("examPlanInfoService")
@Transactional(rollbackFor = Exception.class)
public class ExamPlanInfoService {

    private static Logger logger = LoggerFactory.getLogger(ExamPlanInfoService.class);

    @Autowired
    private ExamineeArrangeMapper examineeArrangeMapper;
    @Autowired
    private ExamScenesMapper examScenesMapper;
    @Autowired
    private ExamRoomMapper examRoomMapper;
    @Autowired
    private ExamSubjectMapper examSubjectMapper;
    @Autowired
    private ExamPlanInfoMapper examPlanInfoMapper;
    @Autowired
    private ExamineeMapper examineeMapper;
    @Autowired
    private ExamMoniterMapper examMoniterMapper;
    @Autowired
    private ExamReportMapper  examReportMapper;
    @Autowired
    private ExamSiteMapper examSiteMapper;
    @Autowired
    private ExamAppMapper examAppMapper;
    @Autowired
    private ExamAdminUserMapper examAdminUserMapper;
    @Autowired
    private ExamAccountAppSiteRelationMapper relationMapper;

    @Resource(name = "customThreadPoolQueue")
    private ExecutorService executor;


    @Value("${ExamSiteURL}")
    private String examSiteURL;
    @Value("${SystemAdmin}")
    private String systemAdmin;
    @Value("${MessageNotifyBaseUrl}")
    private String messageNotifyBaseUrl;
    @Value("${MessageNotifyUrl}")
    private String messageNotifyUrl;

    /**
     * 更具计划id查询计划
     * @return
     */
    public ExamPlanInfo getExamPlanInfoByID(String appID,String examPlanID){
        //查询所有计划 SysState为下载中的数据
        return examPlanInfoMapper.getExamPlanInfo(appID, examPlanID);
    }

    public ExamPlanInfo getExamPlanInfoBySysState(String appID,String examPlanID,Integer sysState){
        //查询所有计划 SysState为下载中的数据
        return examPlanInfoMapper.getExamPlanInfoBySysState(examPlanID, appID, sysState);
    }

    /**
     * 添加导入数据
     * @param examSite
     * @param examApp
     * @param examPlanInfo
     * @param roomList
     * @param examScenesList
     * @param examSubjectList
     * @param examineeList
     * @param examineeArrangeList
     * @param reportList
     * @return
     * @throws Exception
     */
    public Integer addAll(ExamSite examSite, ExamApp examApp, ExamAdminUser adminUser, ExamSiteAppAccountRelation relation, ExamPlanInfo examPlanInfo, List<ExamRoom> roomList, List<ExamScenes> examScenesList, List<ExamSubject> examSubjectList, List<Examinee> examineeList, List<ExamineeArrange> examineeArrangeList, List<ExamReport> reportList, Boolean flag) {
        int i = 0;
        try {
            List<ExamPlanInfo> examPlanInfos = examPlanInfoMapper.findExamPlanListByIdAndState(examPlanInfo.getExamPlanInfoID(), ExamPlanSysState.TestPaperCreated.getPrefix());
            if(!examPlanInfos.isEmpty() && !flag){
                CommonFunction.notifyManager(messageNotifyBaseUrl,messageNotifyUrl,"当前计划已生成，不能进行修改！" + examPlanInfo.getExamPlanInfoID(),(examApp.getManagerPhone() + "," + systemAdmin).split(","));
            }

            //添加考点信息
            examSiteMapper.insertExamSite(examSite);

            //添加项目信息
            examAppMapper.insertExamApp(examApp);

            //添加用户信息
            examAdminUserMapper.insert(adminUser);

            //添加考点用户项目关系
            relationMapper.insert(relation);

            //添加ExamPlanInfo
            examPlanInfoMapper.insertExamPalnInfo(examPlanInfo);

            //添加examRoom
            for (ExamRoom examRoom:roomList) {
                examRoomMapper.insertExamRoom(examRoom);
            }

            //添加examScenes
            for (ExamScenes examScenes:examScenesList) {
                examScenesMapper.insertExamScenes(examScenes);
            }

            //添加ExamSubject
            insertExamSubjectList(examSubjectList);

            //executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
            examineeArrangeList.forEach(examineeArrange -> {
                ExamingMonitor monitor = new ExamingMonitor();
                monitor.setAppID(examineeArrange.getAppID());
                monitor.setExamPlanInfoID(examineeArrange.getExamPlanInfoID());
                monitor.setExamSubjectID(examineeArrange.getExamSubjectID());
                monitor.setExamRoomID(examineeArrange.getExamRoomID());
                monitor.setExamSceneID(examineeArrange.getExamSceneID());
                monitor.setExamineeID(examineeArrange.getExamineeID());
                monitor.setRetainTime(0);
                monitor.setiDCardReason("");
                monitor.setiDCardResult(0);

                CompletableFuture.supplyAsync(() -> examineeArrangeMapper.insertExaminerArrange(examineeArrange),executor);
                CompletableFuture.supplyAsync(() -> examMoniterMapper.insertExamingMoniterAll(monitor),executor);
            });

            //添加Examinee
            for (Examinee examinee:examineeList) {
                examineeMapper.insertExaminee(examinee);
            }

            //添加ExamReport
            for (ExamReport examReport:reportList) {
                examReportMapper.insertExamReport(examReport);
            }

        }catch (Exception e){
            i = -1;
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();examPlanInfo.setSysState(ExamPlanSysState.UNDownload.getPrefix());
            examPlanInfoMapper.updateExamPalnSyState(examPlanInfo);
            logger.error("计划包导入异常！",e);
        }
        return i;
    }

    private void insertExamSubjectList(List<ExamSubject> examSubjects){
        //添加或修改ExamSubject
        for (ExamSubject examSubject:examSubjects) {
            examSubjectMapper.insertExamSubject(examSubject);
        }
    }

    /**
     *
     * @param examPlanID
     * @return
     */
    public List<Map<String,Object>> findExamPlanSubjectCount(String examPlanID){
        return examSubjectMapper.findExamPlanSubjectCount(examPlanID);
    }

    /**
     * 获取所有已开始且已成功加载的批次信息
     * @return
     */
    public List<ExamPlanInfo> findAllStartExamPlanInfo(){
        return examPlanInfoMapper.findAllStartExamPlanInfo();
    }

    /**
     * 更新计划状态
     * @param examPlanInfo
     * @return
     */
    public Integer updateExamPlanSysState(ExamPlanInfo examPlanInfo){
        return examPlanInfoMapper.updateExamPalnSyState(examPlanInfo);
    }

}